﻿
using System;
using System.Text;
using MX.Core.Caching.Redis.Configuration;

namespace MX.Core.Caching.Redis.Sider
{
	public class ProtocolEncoder
	{
		protected const long UnixEpochL = 621355968000000000L;
		// 1st Jan 1970
		protected static readonly DateTime UnixEpoch = new DateTime (UnixEpochL);

		 
		private Encoding _encoding = Encoding.UTF8;

		 
		public ProtocolEncoder ()
		{
			//_buffer = new byte[BufferConfig.EncodingBufferSize];
			  
		}


		public ArraySegment<byte> Encode (byte[] _buffer,string s)
		{
			var bytesNeeded = _encoding.GetByteCount (s);
			if (bytesNeeded <= _buffer.Length) {
				var bytesWrote = _encoding.GetBytes (s, 0, s.Length, _buffer, 0);

				return new ArraySegment<byte> (_buffer, 0, bytesWrote);
			}

			var buffer = _encoding.GetBytes (s);
			return new ArraySegment<byte> (buffer, 0, buffer.Length);
		}

		public string DecodeStr (ArraySegment<byte> buffer)
		{
			return _encoding.GetString (buffer.Array, buffer.Offset, buffer.Count);
		}


		public string Encode (DateTime dt)
		{
			return (dt - UnixEpoch).TotalSeconds.ToString ();
		}

		public DateTime DecodeDateTime (long dateValue)
		{
			return new DateTime (dateValue + UnixEpochL);
		}


		public string Encode (TimeSpan t)
		{
			return    t.TotalSeconds.ToString ();
		}

		public TimeSpan DecodeTimeSpan (long value)
		{
			return TimeSpan.FromSeconds (value);
		}


		public string Encode (double d)
		{
			if (double.IsPositiveInfinity (d))
				return "+inf";
			if (double.IsNegativeInfinity (d))
				return "-inf";

			return     d.ToString ("R");
		}

		public double DecodeDouble (ArraySegment<byte> buffer)
		{
			var str = Encoding.Default.GetString (buffer.Array, buffer.Offset, buffer.Count);

			if (str == "inf" || str == "+inf")
				return double.PositiveInfinity;
			if (str == "-inf")
				return double.NegativeInfinity;

			return   double.Parse (str);
		}
	}
}
